package cn.sh.library.mgts.dto;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregator;
import org.elasticsearch.search.aggregations.metrics.MetricsAggregator;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.boot.configurationprocessor.json.JSONObject;

import com.github.jsonldjava.shaded.com.google.common.base.Strings;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import cn.sh.library.mgts.bean.InstanceSearchBean;
import cn.sh.library.mgts.utils.IPUtils;
import cn.sh.library.mgts.utils.JestUtil;
import cn.sh.library.mgts.utils.StringUtilC;

public class Constructor {
	// 传入SearchResponse 构造成 List<Map<String, Object>> resultList
	public static List<Map<String, Object>> constructorInstance(SearchResponse searchResponse) {
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		SearchHits hist = searchResponse.getHits();

		Iterator<SearchHit> listIt = hist.iterator();
		while (listIt.hasNext()) {
			SearchHit hit = listIt.next();
			JsonObject returnData = new JsonParser().parse(hit.getSourceAsString()).getAsJsonObject();

			Map<String, Object> instance = new HashMap<String, Object>();// instance下数据

			// 责任者 多值
			List<Map<String, Object>> personInfoList = new ArrayList<Map<String, Object>>();// 构造类型-Contribution
			if (!StringUtilC.isEmpty(returnData.get("contribution"))) {
				if (returnData.get("contribution").isJsonArray()) {
					JsonArray array = returnData.get("contribution").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						personInfoList = personList(hit, returnData, personInfoList, size);
					}
				} else {
					personInfoList = personList(hit, returnData, personInfoList, 0);
				}
			}
			//根据serialNo排序
			Collections.sort(personInfoList, new Comparator<Map<String, Object>>() {
				public int compare(Map<String, Object> o1, Map<String, Object> o2) {
					String name1 = o1.get("serialNo").toString();
					String name2 = o2.get("serialNo").toString();
					return name1.compareTo(name2);
				}

			});
			instance.put("personInfoList", personInfoList);

			// 出版信息
			instance.put("provision", JestUtil.getAllJsonStringByPath("provision", returnData, 0));
//			String provision = JestUtil.getAllJsonStringByPath("provision", returnData, 0);
			// 出版信息详情
			List<Map<String, Object>> provisionActivityList = new ArrayList<Map<String, Object>>();// 构造类型-Contribution
			if (!StringUtilC.isEmpty(returnData.get("provisionActivity"))) {
				if (returnData.get("provisionActivity").isJsonArray()) {
					JsonArray array = returnData.get("provisionActivity").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						provisionActivityList = provisionList(instance, hit, returnData, provisionActivityList, size,
								array.get(size));
					}
				} else {
					provisionActivityList = provisionList(instance, hit, returnData, provisionActivityList, 0,
							returnData.get("provisionActivity"));
				}
			}
			instance.put("provisionActivityList", provisionActivityList);
//			instance.put("provision", provision);
			// 发行、制作机构
			List<Map<String, Object>> publications = new ArrayList<Map<String, Object>>();// 构造类型-Contribution
			if (!StringUtilC.isEmpty(returnData.get("publication"))) {
				if (returnData.get("publication").isJsonArray()) {
					JsonArray array = returnData.get("publication").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						publications = shelMarkList(hit, returnData, publications, size, "publish",
								"publication.pubOrganization.@value");
					}
				} else {
					publications = shelMarkList(hit, returnData, publications, 0, "publish",
							"publication.pubOrganization.@value");
				}
			}
			instance.put("publications", publications);
			String isNew = JestUtil.getAllJsonStringByPath("isNew", returnData, 0);
			// 索书号 + 封面 +全文
			List<Map<String, Object>> shelfMarkList = new ArrayList<Map<String, Object>>();
			if (!StringUtilC.isEmpty(returnData.get("item"))) {
				if (returnData.get("item").isJsonArray()) {
					JsonArray array = returnData.get("item").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						shelfMarkList = shelMarkList(hit, returnData, shelfMarkList, size, "shelfmark",
								"item.shelfMark");
						if(array.get(size).getAsJsonObject().has("cover")&& 
								!array.get(size).getAsJsonObject().get("cover").isJsonNull() ) {
							shelfMarkList.get(size).put("cover", array.get(size).getAsJsonObject().get("cover").getAsString());
						}
						if(array.get(size).getAsJsonObject().has("fullTextPath")&& 
								!array.get(size).getAsJsonObject().get("fullTextPath").isJsonNull() ) {
							shelfMarkList.get(size).put("fullTextPath", array.get(size).getAsJsonObject().get("fullTextPath").getAsString());
							if("guotulib".equals(isNew) && !IPUtils.isPrivateIP()) {
								shelfMarkList.get(size).put("fullTextPath", "");
							}
						}
						if(array.get(size).getAsJsonObject().has("doi")&& 
								!array.get(size).getAsJsonObject().get("doi").isJsonNull() ) {
							shelfMarkList.get(size).put("doi", array.get(size).getAsJsonObject().get("doi").getAsString());
						}
						if(array.get(size).getAsJsonObject().has("identifier")&& 
								!array.get(size).getAsJsonObject().get("identifier").isJsonNull() ) {
							shelfMarkList.get(size).put("identifier", array.get(size).getAsJsonObject().get("identifier").getAsString());
						}
						if(array.get(size).getAsJsonObject().has("accessLevel")&& 
								!array.get(size).getAsJsonObject().get("accessLevel").isJsonNull() ) {
							shelfMarkList.get(size).put("accessLevel", array.get(size).getAsJsonObject().get("accessLevel").getAsString());
						}
					}
				} else {
					shelfMarkList = shelMarkList(hit, returnData, shelfMarkList, 0, "shelfmark", "item.shelfMark");
					if(returnData.get("item").getAsJsonObject().has("cover")&& 
							!returnData.get("item").getAsJsonObject().get("cover").isJsonNull() ) {
						shelfMarkList.get(0).put("cover", returnData.get("item").getAsJsonObject().get("cover").getAsString());
					}
					if(returnData.get("item").getAsJsonObject().has("fullTextPath")&& 
							!returnData.get("item").getAsJsonObject().get("fullTextPath").isJsonNull() ) {
						shelfMarkList.get(0).put("fullTextPath", returnData.get("item").getAsJsonObject().get("fullTextPath").getAsString());
						if("guotulib".equals(isNew) && !IPUtils.isPrivateIP()) {
							shelfMarkList.get(0).put("fullTextPath", "");
						}
					}
					if(returnData.get("item").getAsJsonObject().has("doi")&& 
							!returnData.get("item").getAsJsonObject().get("doi").isJsonNull() ) {
						shelfMarkList.get(0).put("doi", returnData.get("item").getAsJsonObject().get("doi").getAsString());
					}
					if(returnData.get("item").getAsJsonObject().has("identifier")&& 
							!returnData.get("item").getAsJsonObject().get("identifier").isJsonNull() ) {
						shelfMarkList.get(0).put("identifier", returnData.get("item").getAsJsonObject().get("identifier").getAsString());
					}
					if(returnData.get("item").getAsJsonObject().has("accessLevel")&& 
							!returnData.get("item").getAsJsonObject().get("accessLevel").isJsonNull() ) {
						shelfMarkList.get(0).put("accessLevel", returnData.get("item").getAsJsonObject().get("accessLevel").getAsString());
					}
//					if(!StringUtilC.isEmpty(returnData.get("item").getAsJsonObject().get("cover"))){
//						shelfMarkList.get(0).put("cover", returnData.get("item").getAsJsonObject().get("cover").toString().replace("\"", ""));
//					}
//					if(!StringUtilC.isEmpty(returnData.get("item").getAsJsonObject().get("fullTextPath"))){
//						shelfMarkList.get(0).put("fullTextPath", returnData.get("item").getAsJsonObject().get("fullTextPath").toString().replace("\"", ""));
//					}
				}
			}
			instance.put("shelfs", shelfMarkList);
			

//			// note 多值拼接
//			instance.put("notes", JestUtil.getAllJsonStringByPath("notes.label", returnData, 0));
			List<Map<String, Object>> noteList = new ArrayList<Map<String, Object>>();
			if (!StringUtilC.isEmpty(returnData.get("notes"))) {
				if (returnData.get("notes").isJsonArray()) {
					JsonArray array = returnData.get("notes").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						noteList = shelMarkList(hit, returnData, noteList, size, "note", "notes.label");
					}
				} else {
					noteList = shelMarkList(hit, returnData, noteList, 0, "note", "notes.label");
				}
			}
			instance.put("notes", noteList);

			// 并列题名（parallelTitles-title）
			List<Map<String, Object>> parallelTitles = new ArrayList<Map<String, Object>>();
			if (!StringUtilC.isEmpty(returnData.get("ParallelTitle"))) {
				if (returnData.get("ParallelTitle").isJsonArray()) {
					JsonArray array = returnData.get("ParallelTitle").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						parallelTitles = shelMarkList(hit, returnData, parallelTitles, size, "title",
								"ParallelTitle.mainTitle");
					}
				} else {
					parallelTitles = shelMarkList(hit, returnData, parallelTitles, 0, "title",
							"ParallelTitle.mainTitle");
				}
			}
			instance.put("parallelTitles", parallelTitles);

			// 语言（多值） 只取正文语种
			instance.put("language", JestUtil.getAllJsonStringByPath("workUri.workLanguage.@value", returnData, 0));
			List<Map<String, Object>> languageList = new ArrayList<Map<String, Object>>();
			if (!StringUtilC.isEmpty(returnData.get("workUri").getAsJsonObject().get("language"))) {
				if (returnData.get("workUri").getAsJsonObject().get("language").isJsonArray()) {
					JsonArray array = returnData.get("workUri").getAsJsonObject().get("language").getAsJsonArray();
					for (int size = 0; size < array.size(); size++) {
						JsonElement langEle = array.get(size);
						if ("正文语种".equals(
								langEle.getAsJsonObject().get("workLanguagePart").toString().replace("\"", ""))) {
							String language = langEle.getAsJsonObject().get("workLanguage").getAsJsonObject()
									.get("@value").toString().replace("\"", "");
							instance.put("language", language);
						}
					}
				} else {
					JsonElement langEle = returnData.get("workUri").getAsJsonObject().get("language");
					if ("正文语种".equals(langEle.getAsJsonObject().get("workLanguagePart").toString().replace("\"", ""))) {
						String language = langEle.getAsJsonObject().get("workLanguage").getAsJsonObject().get("@value")
								.toString().replace("\"", "");
						instance.put("language", language);
					}
				}
			}
			// 题名 单值
			// 高亮值获取

			highlight(0, hit, returnData, instance, "title.label.@value", "title");

			// 尺寸
			instance.put("dimensions", JestUtil.getAllJsonStringByPath("dimensions", returnData, 0));
			// 价格
			instance.put("terms", JestUtil.getAllJsonStringByPath("terms", returnData, 0));
			// 页码
			instance.put("page", JestUtil.getAllJsonStringByPath("page", returnData, 0));
			// 作品题名
			instance.put("workTitle", JestUtil.getAllJsonStringByPath("workUri.workTitle.@value", returnData, 0));

			// 内容提要
			instance.put("summary", JestUtil.getAllJsonStringByPath("summary", returnData, 0));

			// 主要责任者
			instance.put("creator", JestUtil.getAllJsonStringByPath("workUri.workCreator", returnData, 0));

			// year
//			instance.put("year", JestUtil.getAllJsonStringByPath("creationDate", returnData, 0));

			// uri
			instance.put("uri", JestUtil.getAllJsonStringByPath("@id", returnData, 0));

			// workUri
			instance.put("workUri", JestUtil.getAllJsonStringByPath("workUri.@id", returnData, 0));
			
			//classPortion
			if(returnData.has("classPortion")) {
				List<String> claszes = new ArrayList<>();
				if(returnData.get("classPortion").isJsonArray()) {
					for (JsonElement element : returnData.get("classPortion").getAsJsonArray()) {
						claszes.add(element.getAsString());
					}
				}else {
					claszes.add(returnData.get("classPortion").getAsString());
				}
				instance.put("classPortion", claszes);
			}

			// 主题词
//			instance.put("subject", JestUtil.getAllJsonStringByPath("workUri.workSubject", returnData, 0));
			if(returnData.get("workUri").getAsJsonObject().has("workSubject")) {
				JsonElement workSubject = returnData.get("workUri").getAsJsonObject().get("workSubject");
				List<String> subjects = new ArrayList<String>();
				if(workSubject.isJsonArray()) {
					for (JsonElement element : workSubject.getAsJsonArray()) {
						subjects.add(element.getAsString());
					}
				}else {
					subjects.add(workSubject.getAsString());
				}
				instance.put("subject", subjects);
			}
			if(returnData.has("complexSubject")) {
				List<String> subjects = new ArrayList<String>();
				for (JsonElement element : returnData.get("complexSubject").getAsJsonArray()) {
					subjects.add(element.getAsJsonObject().get("labelConcat").getAsString());
				}
				instance.put("subject", subjects);
			}

			// 丛书
			instance.put("series", JestUtil.getAllJsonStringByPath("seriesLabel", returnData, 0));

			// 分类
			instance.put("classUri", JestUtil.getAllJsonStringByPath("classification.@id", returnData, 0));

			instance.put("classCode", JestUtil.getAllJsonStringByPath("classification.code", returnData, 0));

			instance.put("classLevel", JestUtil.getAllJsonStringByPath("classification.level", returnData, 0));

			

			resultList.add(instance);
		}
		return resultList;
	}

	private static List<Map<String, Object>> personList(SearchHit hit, JsonObject sourceJsonObj,
			List<Map<String, Object>> returnList, int size) {
		Map<String, Object> personInfo = new HashMap<String, Object>();
		// 放入personName字段
		if (StringUtils
				.isNotEmpty(JestUtil.getAllJsonStringByPath("contribution.personName.@value", sourceJsonObj, size))) {
//			personInfo.put("personName",
//					JestUtil.getAllJsonStringByPath("contribution.personName", sourceJsonObj, size));
			highlight(size, hit, sourceJsonObj, personInfo, "contribution.personName.@value", "personName");
		}
		// 放入personRole字段s
		if (StringUtils.isNotEmpty(JestUtil.getAllJsonStringByPath("contribution.personRole", sourceJsonObj, size))) {
			personInfo.put("personRole",
					JestUtil.getAllJsonStringByPath("contribution.personRole", sourceJsonObj, size));
		}
		// 放入personUri字段
		if (StringUtils
				.isNotEmpty(JestUtil.getAllJsonStringByPath("contribution.personUri.@id", sourceJsonObj, size))) {
			personInfo.put("personUri",
					JestUtil.getAllJsonStringByPath("contribution.personUri.@id", sourceJsonObj, size));
		}
		// 放入person-serialNo字段
		if (StringUtils.isNotEmpty(JestUtil.getAllJsonStringByPath("contribution.serialNo", sourceJsonObj, size))) {
			personInfo.put("serialNo", JestUtil.getAllJsonStringByPath("contribution.serialNo", sourceJsonObj, size));
		}
		if (personInfo.size() > 0) {
			returnList.add(personInfo);
		}
		return returnList;
	}

	private static List<Map<String, Object>> provisionList(Map<String, Object> instance, SearchHit hit,
			JsonObject returnData, List<Map<String, Object>> returnList, int size, JsonElement inData) {
		Map<String, Object> provisionActivity = new HashMap<String, Object>();
		if (StringUtils.isNotEmpty(JestUtil.getAllJsonStringByPath("provisionActivity.proDate", returnData, size))) {
			provisionActivity.put("proDate",
					JestUtil.getAllJsonStringByPath("provisionActivity.proDate", returnData, size));
		}
		if (StringUtils.isNotEmpty(
				JestUtil.getAllJsonStringByPath("provisionActivity.proOrganization.@value", returnData, size))) {

			provisionActivity.put("proOrganization",
					JestUtil.getAllJsonStringByPath("provisionActivity.proOrganization.@value", returnData, size));// 空节点或uri数组
			highlightPro(instance, hit, returnData, provisionActivity, "provisionActivity.proOrganization.@value",
					"proOrganization");

		} else if (
		// 特殊情况 机构为数组形式 元素为1
		StringUtils
				.isEmpty(JestUtil.getAllJsonStringByPath("provisionActivity.proOrganization.@value", returnData, size))
				&& !StringUtilC.isEmpty(inData.getAsJsonObject().get("proOrganization"))) {
			if (inData.getAsJsonObject().get("proOrganization").isJsonArray()) {
				String orgName = inData.getAsJsonObject().get("proOrganization").getAsJsonArray().get(0)
						.getAsJsonObject().get("@value").toString().replace("\"", "");
				provisionActivity.put("proOrganization", orgName);// 空节点或uri数组
				highlightPro(instance, hit, returnData, provisionActivity, "provisionActivity.proOrganization.@value",
						"proOrganization");
			}

		}
		if (StringUtils
				.isNotEmpty(JestUtil.getAllJsonStringByPath("provisionActivity.proPlace.@value", returnData, size))) {

			provisionActivity.put("proPlace",
					JestUtil.getAllJsonStringByPath("provisionActivity.proPlace.@value", returnData, size));
			highlightPro(instance, hit, returnData, provisionActivity, "provisionActivity.proPlace.@value", "proPlace");

		}
		if (StringUtils
				.isNotEmpty(JestUtil.getAllJsonStringByPath("provisionActivity.proPlaceUri.@id", returnData, size))) {
			provisionActivity.put("proPlaceUri",
					JestUtil.getAllJsonStringByPath("provisionActivity.proPlaceUri.@id", returnData, size));
		}
		if (provisionActivity.size() > 0) {
			returnList.add(provisionActivity);
		}
		return returnList;
	}

	// 索书号
	private static List<Map<String, Object>> shelMarkList(SearchHit hit, JsonObject returnData,
			List<Map<String, Object>> returnList, int size, String a, String b) {
		Map<String, Object> shelfMark = new HashMap<String, Object>();
//		shelfMark.put(a, JestUtil.getAllJsonStringByPath(b, sourceJsonObj, size));
		highlight(size, hit, returnData, shelfMark, b, a);
		returnList.add(shelfMark);
		return returnList;
	}

	// 构造分类的结构
	public static List<Map<String, Object>> constructClass(SearchResponse searchResponse) {
		List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
		Map<String, Object> classLevel1 = new HashMap<String, Object>();
		Map<String, Object> classLevel2 = new HashMap<String, Object>();
		Map<String, Object> classLevel3 = new HashMap<String, Object>();
		Map<String, Object> classLevel4 = new HashMap<String, Object>();
		Map<String, Object> classLevel5 = new HashMap<String, Object>();
		Map<String, Object> classLevel6 = new HashMap<String, Object>();
		Map<String, Object> classLevel7 = new HashMap<String, Object>();
		SearchHits hist = searchResponse.getHits();
		Iterator<SearchHit> listIt = hist.iterator();
		while (listIt.hasNext()) {
			JsonObject returnData = new JsonParser().parse(listIt.next().getSourceAsString()).getAsJsonObject();
			String levelStr = JestUtil.getAllJsonStringByPath("level.@value", returnData, 0);
			int level = (levelStr.length() + 1) / 4;
			Map<String, Object> classLevel = new HashMap<>();
			classLevel = constructClass(returnData, classLevel);
			switch (level) {
			case 1:
				if (classLevel1.size() > 0) {
					resultList.add(classLevel1);
				}
				classLevel1 = classLevel;
				break;
			case 2:
				classLevel2 = classLevel;
				constructClassLevel(classLevel2, classLevel1);
				break;
			case 3:
				classLevel3 = classLevel;
				constructClassLevel(classLevel3, classLevel2);
				break;
			case 4:
				classLevel4 = classLevel;
				constructClassLevel(classLevel4, classLevel3);
				break;
			case 5:
				classLevel5 = classLevel;
				constructClassLevel(classLevel5, classLevel4);
				break;
			case 6:
				classLevel6 = classLevel;
				constructClassLevel(classLevel6, classLevel5);
				break;
			case 7:
				classLevel7 = classLevel;
				constructClassLevel(classLevel7, classLevel6);
				break;
			default:
				break;
			}
		}
		resultList.add(classLevel1);
		return resultList;

	}

	private static void highlight(int size, SearchHit hit, JsonObject sourceJsonObj, Map<String, Object> returnMap,
			String key, String putKey) {
		String getValue = JestUtil.getAllJsonStringByPath(key, sourceJsonObj, size);
		Map<String, HighlightField> highlightField = hit.getHighlightFields();
		HighlightField highValue = highlightField.get(key);// 高量值
		if (highValue != null) {
			Text[] fragments = highValue.fragments();
			String newHighValue = "";
			for (Text text : fragments) {
				newHighValue = text.toString();
			}
			String value = newHighValue.replace("<b style='color:red'>", "").replace("</b>", "");
			if (value.equals(getValue)) {
				returnMap.put(putKey, newHighValue);
			} else {
				returnMap.put(putKey, JestUtil.getAllJsonStringByPath(key, sourceJsonObj, size));
			}
		} else {
			returnMap.put(putKey, JestUtil.getAllJsonStringByPath(key, sourceJsonObj, size));
		}
	}

	private static void highlightPro(Map<String, Object> instance, SearchHit hit, JsonObject sourceJsonObj,
			Map<String, Object> returnMap, String key, String putKey) {
		Map<String, HighlightField> highlightField = hit.getHighlightFields();
		HighlightField highValue = highlightField.get(key);// 高量值
		if (highValue != null) {
			Text[] fragments = highValue.fragments();
			String newHighValue = "";
			for (Text text : fragments) {
				newHighValue = text.toString();
			}
			String value = newHighValue.replace("<b style='color:red'>", "").replace("</b>", "");
			String pro = instance.get("provision").toString().replace(value, newHighValue);
			instance.remove("provision");
			instance.put("provision", pro);
//			returnMap.put(putKey, newHighValue);
		} else {
//			returnMap.put(putKey, JestUtil.getAllJsonStringByPath(key, sourceJsonObj,0));
		}
	}

	private static Map<String, Object> constructClass(JsonObject returnData, Map<String, Object> classLevel) {
//		classLevel.put("broaderUri", JestUtil.getAllJsonStringByPath("broader.@id", returnData, 0));
//		classLevel.put("code", JestUtil.getAllJsonStringByPath("code.@value", returnData, 0));
//		classLevel.put("prefLabel", JestUtil.getAllJsonStringByPath("prefLabel.@value", returnData, 0));
		classLevel.put("title", JestUtil.getAllJsonStringByPath("code.@value", returnData, 0) + " "
				+ JestUtil.getAllJsonStringByPath("prefLabel.@value", returnData, 0));
//		classLevel.put("level", JestUtil.getAllJsonStringByPath("level.@value", returnData, 0));
		classLevel.put("key", JestUtil.getAllJsonStringByPath("level.@value", returnData, 0));
//		classLevel.put("uri", JestUtil.getAllJsonStringByPath("@id", returnData, 0));
		return classLevel;
	}

	private static void constructClassLevel(Map<String, Object> classLevelSelf, Map<String, Object> classLevelBorder) {
		if (classLevelBorder.get("children") != null) {
			List<Map<String, Object>> childrenList = (List<Map<String, Object>>) classLevelBorder.get("children");
			childrenList.add(childrenList.size(), classLevelSelf);
		} else {
			List<Map<String, Object>> childrenList = new ArrayList<>();
			childrenList.add(classLevelSelf);
			classLevelBorder.put("children", childrenList);
		}
	}
}
